package com.cnap.service.impl;

import cn.hutool.core.util.IdUtil;
import com.cnap.CnapApplicationTests;
import com.cnap.db.entity.FileInfoPO;
import com.cnap.db.entity.MicroServicePO;
import com.cnap.db.entity.PatchInfoPO;
import com.cnap.db.entity.ProgressPO;
import com.cnap.db.mapper.FileMapper;
import com.cnap.db.mapper.MicroServiceMapper;
import com.cnap.db.mapper.ProgressMapper;
import com.cnap.model.exception.JsonException;
import com.cnap.model.file.FileConstants;
import com.cnap.model.progress.ProgressConstants;
import com.cnap.model.progress.ProgressVO;
import com.cnap.model.progress.ProgressVOForSplit;
import com.cnap.service.ApplicationService;
import com.cnap.service.ProgressService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.time.LocalDateTime;
import java.util.Collections;

/**
 * <类文件描述>
 *
 * @author xc
 **/
class ProgressServiceImplTest extends CnapApplicationTests {

    @Autowired
    private ProgressService progressService;

    @MockBean
    private ProgressMapper progressMapper;

    @MockBean
    private FileMapper fileMapper;

    @MockBean
    private MicroServiceMapper microServiceMapper;

    @Test
    void getProgressByApplicationIdWithNull() {
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(null);
        ApplicationService applicationService = Mockito.mock(ApplicationService.class);
        //spingUtilMockedStatic.when(() -> SpringUtil.getBean(ApplicationService.class)).thenReturn(applicationService);
        //Mockito.when(applicationService.deleteApplicationById("1")).thenReturn(true);
        Assertions.assertThrows(JsonException.class, () -> {
            progressService.getProgressByApplicationId("1");
        });
    }

    @Test
    void getProgressByApplicationIdWithProgressExp() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setException("异常了");
        Mockito.when(progressMapper.selectProgressById("1")).thenReturn(progressPO);

        Assertions.assertThrows(JsonException.class, () -> {
            progressService.getProgressByApplicationId("1");
        });
    }

    @Test
    void getProgressByApplicationId() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(10);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        PatchInfoPO patchInfoPO = new PatchInfoPO();
        patchInfoPO.setId(IdUtil.simpleUUID());
        patchInfoPO.setPatchSize(100);
        patchInfoPO.setIndex(1);
        patchInfoPO.setStatus(1);
        patchInfoPO.setParentId("1");
        patchInfoPO.setFileName("fileName.zip");

        Mockito.when(fileMapper.selectByParentId("1")).thenReturn(Collections.singletonList(patchInfoPO));

        ProgressVO vo = progressService.getProgressByApplicationId("1");

        Assertions.assertEquals(10, vo.getPercent());
    }

    @Test
    void getProgressPOByApplicationIdWithNull() {
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(null);

        Assertions.assertThrows(JsonException.class, () -> {
            progressService.getProgressPOByApplicationId("1");
        });
    }

    @Test
    void getProgressPOByApplicationId() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(10);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        ProgressPO po = progressService.getProgressPOByApplicationId("1");

        Assertions.assertNotNull(po);
    }

    @Test
    void getProgressForSplitByApplicationIdWithNull() {
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(null);

        Assertions.assertThrows(JsonException.class, () -> {
            progressService.getProgressForSplitByApplicationId("1");
        });
    }


    @Test
    void getProgressForSplitByApplicationIdWithExp() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setException("异常了");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        Assertions.assertThrows(JsonException.class, () -> {
            progressService.getProgressForSplitByApplicationId("1");
        });
    }

    @Test
    void getProgressForSplitByApplicationId() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(11);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        MicroServicePO microServicePO = new MicroServicePO();
        microServicePO.setId(IdUtil.simpleUUID());
        microServicePO.setServiceName("service-name");
        microServicePO.setApplicationName("app_name");
        microServicePO.setSize("400MB");
        microServicePO.setUpdateTime(LocalDateTime.now());
        microServicePO.setUserName("admin");

        Mockito.when(microServiceMapper.selectMicroServiceByAppId("1")).thenReturn(Collections.singletonList(microServicePO));

        ProgressVOForSplit vo = progressService.getProgressForSplitByApplicationId("1");

        Assertions.assertEquals(11 , vo.getPercent());
    }

    @Test
    void initProgressWithSame() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(11);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        boolean result = progressService.initProgress(progressPO);

        Assertions.assertTrue(result);
    }

    @Test
    void initProgressWithUpdate() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);
        Mockito.when(progressMapper.updateProgress(Mockito.any())).thenReturn(1);

        boolean result = progressService.initProgress(progressPO);

        Assertions.assertTrue(result);
    }

    @Test
    void initProgress() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(null);
        Mockito.when(progressMapper.saveProgress(Mockito.any())).thenReturn(1);

        boolean result = progressService.initProgress(progressPO);

        Assertions.assertTrue(result);
    }

    @Test
    void updateProgressWithNull() {
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(null);
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        boolean result = progressService.updateProgress(progressPO);

        Assertions.assertFalse(result);
    }

    @Test
    void updateProgress() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);
        Mockito.when(progressMapper.updateProgress(Mockito.any())).thenReturn(1);
        boolean result = progressService.updateProgress(progressPO);

        Assertions.assertTrue(result);
    }

    @Test
    void updateProgressPercent() {
        Mockito.when(progressMapper.updateProgress(Mockito.any())).thenReturn(1);
        boolean result = progressService.updateProgressPercent("1", 78);

        Assertions.assertTrue(result);
    }

    @Test
    void updateProgressException() {
        Mockito.when(fileMapper.updatePatchInfoStatusByParentId("1", FileConstants.PATCH_STATUS_FAILED)).thenReturn(1);
        Mockito.when(progressMapper.updateProgress(Mockito.any())).thenReturn(1);

        boolean result = progressService.updateProgressException("1", "异常");

        Assertions.assertTrue(result);
    }

    @Test
    void getPercentByApplicationId() {
        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        int percent = progressService.getPercentByApplicationId("1");

        Assertions.assertEquals(16, percent);
    }

    @Test
    void calPercentWithOnePatchAndUpdate() {
        PatchInfoPO patchInfoPO = new PatchInfoPO();
        patchInfoPO.setId(IdUtil.simpleUUID());
        patchInfoPO.setPatchSize(100);
        patchInfoPO.setIndex(1);
        patchInfoPO.setStatus(1);
        patchInfoPO.setParentId("1");
        patchInfoPO.setFileName("fileName.zip");

        FileInfoPO fileInfoPO = new FileInfoPO();
        fileInfoPO.setId("1");
        fileInfoPO.setPatchNums(1);
        Mockito.when(fileMapper.selectByParentId("1")).thenReturn(Collections.singletonList(patchInfoPO));
        Mockito.when(fileMapper.selectById("1")).thenReturn(fileInfoPO);

        ProgressPO progressPO = new ProgressPO();
        progressPO.setPercent(16);
        progressPO.setStage(ProgressConstants.STAGE_UPLOAD_PATCH);
        progressPO.setType(ProgressConstants.TYPE_UPLOAD);
        progressPO.setId("1");
        Mockito.when(progressMapper.selectProgressById(Mockito.anyString())).thenReturn(progressPO);

        Assertions.assertDoesNotThrow(()->{
            progressService.calPercentWithOnePatchAndUpdate("1");
        });
    }
}